/*
 * Copyright 2019 Zhang XueHai
 * you may not use this file except in compliance with the License.
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.zhangxuehai.android.pdfviewer;

import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.PorterDuff;
import android.graphics.Rect;
import android.graphics.RectF;
import android.util.SparseArray;
import com.zhangxuehai.android.pdfviewer.annotation.BaseAnnotation;
import com.shockwave.pdfium.util.Size;
import com.shockwave.pdfium.util.SizeF;
import java.util.ArrayList;
import java.util.List;

/**
 * 注释绘画管理器</br>
 * 负责绘制 {{@link AnnotationManager}}中的注释
 * @author 章学海
 * @date 2019/12/26
 */
final class AnnotationDrawManager {
    /**
     * 基础画笔线框系数
     * */
    private static final int BASE_PEN_WIDTH_COEFFICIENT = 100;

    private PDFView pdfView;
    private AnnotationManager annotationManager;
    /**bitmap缓存*/
    SparseArray<Bitmap> cache = new SparseArray<>();
    /**绘制中注释的画布*/
    private Bitmap drawingBitmap;
    /**画笔，绘制bitmap到大画布上*/
    private Paint paint;

    AnnotationDrawManager(PDFView pdfView, AnnotationManager annotationManager) {
        this.pdfView = pdfView;
        this.annotationManager = annotationManager;
        paint =new Paint(Paint.ANTI_ALIAS_FLAG);
        paint.setFilterBitmap(true);
        paint.setDither(true);
    }

    /**绘制*/
    public void draw(Canvas canvas, int page) {
        //绘制需要的一些参数
        SizeF size = pdfView.pdfFile.getPageSize(page);
        float zoom = pdfView.getZoom();
        Rect rect = new Rect(0,0,(int)size.getWidth(),(int)size.getHeight());
        RectF rectF = new RectF(0,0,size.getWidth()*zoom,size.getHeight()*zoom);
        Size pdfSize = pdfView.pdfFile.originalPageSizes.get(page);
        float scale = pdfSize.getWidth()/size.getWidth();
        // 移动到正确位置
        float localTranslationX;
        float localTranslationY;
        if (pdfView.isSwipeVertical()) {
            localTranslationY = pdfView.pdfFile.getPageOffset(page, zoom);
            float maxWidth = pdfView.pdfFile.getMaxPageWidth();
            localTranslationX = (maxWidth - size.getWidth()) * zoom / 2;
        } else {
            localTranslationX = pdfView.pdfFile.getPageOffset(page, zoom);
            float maxHeight = pdfView.pdfFile.getMaxPageHeight();
            localTranslationY = (maxHeight - size.getHeight())*zoom / 2;
        }
        canvas.translate(localTranslationX, localTranslationY);
        //画 注释
        drawAnnotation(canvas,page,rect,rectF,scale);
        //画 橡皮擦
        drawEraser(canvas,page,rect,rectF,scale);
        // 移动到原来的位置
        canvas.translate(-localTranslationX, -localTranslationY);
    }
    /**
     * 画橡皮擦
     * */
    private void drawEraser(Canvas canvas,int page,Rect pageSize,RectF drawRegion,float scale){
        if(
                pdfView.getFunction() == PDFView.Function.ERASER &&
                        annotationManager.eraser !=null &&
                        annotationManager.eraserPage == page
        ){
            if(drawingBitmap == null){
                drawingBitmap = Bitmap.createBitmap(pageSize.width(),pageSize.height(),Bitmap.Config.ARGB_8888);
            }else{
                if(drawingBitmap.getWidth() != pageSize.width() || drawingBitmap.getHeight() != pageSize.height()){
                    drawingBitmap.recycle();
                    drawingBitmap = Bitmap.createBitmap(pageSize.width(),pageSize.height(),Bitmap.Config.ARGB_8888);
                }
            }
            Canvas drawingCanvas = new Canvas(drawingBitmap);
            drawingCanvas.drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR);
            annotationManager.eraser.draw(drawingCanvas,scale,pdfView.getZoom());
            canvas.drawBitmap(drawingBitmap,pageSize,drawRegion, paint);
        }
    }
    /**
     * 画注释
     * @param canvas 画布
     * @param page 需要绘画的页码
     * @param pageSize 当前页码在display坐标上的大小
     * @param drawRegion bitmap画在canvas上的区域
     * @param scale 解析出来的pdf页码大小 于 display坐标dpf页码大小的比
     * */
    private void drawAnnotation(Canvas canvas, int page, Rect pageSize, RectF drawRegion, float scale) {
        List<BaseAnnotation> annotations = annotationManager.annotations.get(page);
        //没有需要绘制的注释
        boolean emptyAnnotation = annotations == null || annotations.size() == 0;
        //没用需要绘制的正在绘制的注释
        boolean emptyDrawingAnnotaion = annotationManager.drawingAnnotation ==null ||
                annotationManager.drawingAnnotation.page != page ||
                annotationManager.drawingAnnotation.data == null;
        //如果不需要绘制，跳过绘制
        boolean needSkip = emptyAnnotation && emptyDrawingAnnotaion;
        if(needSkip){
            return;
        }
        if(!emptyAnnotation){
            drawDrawedAnnotation(canvas,page,pageSize,drawRegion,scale,annotations);
        }
        if(!emptyDrawingAnnotaion){
            drawDrawingAnnotation(canvas,page,pageSize,drawRegion,scale,annotationManager.drawingAnnotation);
        }
    }
    /**绘制完成编辑的注释*/
    private void drawDrawedAnnotation(Canvas canvas, int page, Rect pageSize, RectF drawRegion, float scale,List<BaseAnnotation> annotations){
        //获取缓存的bitmap
        Bitmap bm = cache.get(page);
        //如果bitmap 为空创建，如果bitmap的尺寸不是需要的bitmap回收原页面并重新创建
        if(bm==null){
            bm = Bitmap.createBitmap(pageSize.width(),pageSize.height(),Bitmap.Config.ARGB_8888);
        }else{
            if(bm.getWidth() != pageSize.width() || bm.getHeight() != pageSize.height()){
                bm.recycle();
                bm = Bitmap.createBitmap(pageSize.width(),pageSize.height(),Bitmap.Config.ARGB_8888);
                setRecycleAnnotationPageUnDraw(page);
            }
        }
        //加入缓存
        cache.put(page,bm);
        //需要绘画页面pdf解析尺寸
        Size pdfSize = pdfView.pdfFile.originalPageSizes.get(page);
        //基础画笔线框 最小宽/高 除以 100
        int basePenWidth = Math.min(pdfSize.getHeight(),pdfSize.getWidth());
        basePenWidth /=BASE_PEN_WIDTH_COEFFICIENT;
        //各个注释绘画
        Canvas pageCanvas = new Canvas(bm);
        if(annotations!=null && annotations.size()>0){
            for (BaseAnnotation annotation : annotations) {
                //以及绘制过的注释不需要再次绘画
                if(!annotation.drawed){
                    annotation.draw(pageCanvas,scale,basePenWidth,pdfView);
                }
            }
        }
        //绘制在大的画布上
        canvas.drawBitmap(bm,pageSize,drawRegion, paint);
    }
    /**绘制正在编辑的注释*/
    private void drawDrawingAnnotation(Canvas canvas, int page, Rect pageSize, RectF drawRegion, float scale, BaseAnnotation drawingAnnotation){
        //如果bitmap 为空创建，如果bitmap的尺寸不是需要的bitmap重新创建
        if(drawingBitmap == null){
            drawingBitmap = Bitmap.createBitmap(pageSize.width(),pageSize.height(),Bitmap.Config.ARGB_8888);
        }else{
            if(drawingBitmap.getWidth() != pageSize.width() || drawingBitmap.getHeight() != pageSize.height()){
                drawingBitmap.recycle();
                drawingBitmap = Bitmap.createBitmap(pageSize.width(),pageSize.height(),Bitmap.Config.ARGB_8888);
            }
        }
        Canvas drawingCanvas = new Canvas(drawingBitmap);
        //清空画布
        drawingCanvas.drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR);
        //基础画笔线框 最小宽/高 除以 100
        Size pdfSize = pdfView.pdfFile.originalPageSizes.get(page);
        int basePenWidth = Math.min(pdfSize.getHeight(),pdfSize.getWidth());
        basePenWidth /=BASE_PEN_WIDTH_COEFFICIENT;
        //绘制注释
        drawingAnnotation.draw(drawingCanvas,scale,basePenWidth,pdfView);
        drawingAnnotation.drawed = false;
        //绘制到大画布上
        canvas.drawBitmap(drawingBitmap,pageSize,drawRegion, paint);
    }
    /**
     * 不需要绘制的bitmap给予释放
     * @param pages 不用回收的页
     * */
    void recycle(List<Integer> pages){
        List<Integer> recyclePage = new ArrayList<>();
        for (int i = 0; i < cache.size(); i++) {
            if(!pages.contains(cache.keyAt(i))){
                recyclePage.add(cache.keyAt(i));
            }
        }
        for (Integer page : recyclePage) {
            Bitmap bm = cache.get(page);
            if(bm!=null && !bm.isRecycled()){
                bm.recycle();
            }
            cache.remove(page);
            setRecycleAnnotationPageUnDraw(page);
        }
    }
    /**
     * 设置被回收的页码的注释为未绘制状态
     * */
    private void setRecycleAnnotationPageUnDraw(int page){
        List<BaseAnnotation> list = annotationManager.annotations.get(page);
        if(list == null || list.size() == 0){
            return;
        }
        for (BaseAnnotation annotation : list) {
            annotation.drawed = false;
        }
    }
}
